package seatiger.tomcat.catalina.connector;

import seatiger.tomcat.catalina.*;
import seatiger.tomcat.catalina.connector.http.HttpProcessor;
import seatiger.tomcat.catalina.connector.http.HttpRequestImpl;
import seatiger.tomcat.catalina.connector.http.HttpResponseImpl;
import seatiger.tomcat.catalina.util.LifecycleSupport;

import java.io.IOException;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.*;

@Deprecated
public class HttpConnector extends AbstractConnector implements Runnable {
    private volatile boolean stopped = false;
    private ServerSocket serverSocket = null;
    private int port;
    private String threadName;
    /**
     * 存放处理器的池子
     */
    private Stack<HttpProcessor> processors = new Stack();

    /**
     * 已创建的HttpProcessor
     */
    private List<HttpProcessor> created = new ArrayList<>();

    private int minProcessors = 5;
    //-1 则不受限制
    private int maxProcessors = 20;
    //多少个已经创建了
    private int curProcessors = 0;

    private Thread thread = null;
    @Override
    public void run() {
        while (!stopped){
            Socket socket = null;
            try {
                //阻塞等待连接
                socket = serverSocket.accept();
            }catch (Exception e){
                e.printStackTrace();
                continue;
            }
            HttpProcessor processor = createProcessor();
            if (processor == null){
                try {
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            //唤醒线程
            processor.assign(socket);
        }
    }


    @Override
    public void start() throws LifecycleException{
        if (started){
            throw new LifecycleException("httpConnector.alreadyStarted");
        }
        threadName = "HttpConnector[" + port + "]";
        //触发connect的开始启动的事件
        lifecycle.fireLifecycleEvent(Lifecycle.START_EVENT,null);
        started = true;
        threadStart();
        //可以提交创建好一部分HttpProcessor
        while (curProcessors < minProcessors){
            if (maxProcessors > 0 && curProcessors >= minProcessors){
                break;
            }
            HttpProcessor processor = newProcessor();
            recycle(processor);
        }
    }

    public void threadStart(){
        thread = new Thread(this, threadName);
        thread.setDaemon(true);
        thread.start();
    }




    @Override
    public void initialize() throws LifecycleException{
        if (initialized){
            throw new LifecycleException("has initialized");
        }
        try {
            serverSocket = new ServerSocket(port);
        }catch (Exception e){
            e.printStackTrace();
            System.exit(1);
        }
    }



    /**
     * 创建池子
     * @return
     */
    private HttpProcessor createProcessor(){
        synchronized (processors){
            if (processors.size() > 0){
                return processors.pop();
            }else if(maxProcessors > 0 && curProcessors < maxProcessors){
                return newProcessor();
            }else {
                if (maxProcessors < 0){
                    return newProcessor();
                }else {
                    return null;
                }
            }
        }
    }

    /**
     * 创建一个新HttpProcessor对象
     * @return
     */
    private HttpProcessor newProcessor(){
        HttpProcessor processor = new HttpProcessor(this,curProcessors++);
        try {
            startComponents(processor);
        } catch (LifecycleException e) {
            return null;
        }
        created.add(processor);
        return processor;
    }

    public void setPort(int port) {
        this.port = port;
    }

    public int getPort() {
        return port;
    }

    /**
     * 将HttpProcessor 放回池子
     * @param processor
     */
    public void recycle(HttpProcessor processor) {
        processors.push(processor);
    }

    @Override
    public void stop() throws LifecycleException {
        if (!started)
            throw new LifecycleException("httpConnector.notStarted");
        lifecycle.fireLifecycleEvent(STOP_EVENT, null);
        started = false;

        created.forEach(h -> {
            try {
                stopComponents(h);
            } catch (LifecycleException e) {
                e.printStackTrace();
            }
        });

        if (serverSocket != null){
            try {
                serverSocket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        threadStop();
        serverSocket = null;
    }

    private void threadStop() {
        stopped = true;
        thread = null;
    }
}
